package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.heima.apis.article.IArticleClient;
import com.heima.audit.aliyun.GreenImageScan;
import com.heima.audit.aliyun.GreenTextScan3;
import com.heima.common.constants.WemediaConstants;
import com.heima.common.constants.WmNewsMessageConstants;
import com.heima.common.exception.CustomException;
import com.heima.file.service.FileStorageService;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.*;
import com.heima.utils.common.ThreadLocalUtil;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.avro.data.Json;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 自媒体图文内容信息表 服务实现类
 * </p>
 *
 * @author itheima
 */
@Slf4j
@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Autowired
    private WmNewsMaterialService wmNewsMaterialService;

    @Autowired
    private WmMaterialService wmMaterialService;

    @Autowired
    private WmNewsAuditService wmNewsAuditService;


    /**
     * 自媒体文章提交审核 发布草稿
     */
    @Transactional
    @Override
    public ResponseResult submit(WmNewsDto dto,Integer isSubmit) {
        log.info("自媒体文章提交审核或发布草稿开始 dto =======>>> {},isSubmit ====>>{}", dto,isSubmit);
        // 保证业务严谨性：参数值是否为空/不为空？ 参数值是否符合要求？ 判断业务数据是否存在/不存在？ 判断数据的状态是否允许继续往下执行？
        //1. 数据准入判断：判断标题和内容等参数是否为空
        if (StringUtils.isBlank(dto.getTitle()) || StringUtils.isBlank(dto.getContent())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }


        //2. 创建或更新文章
        //2.1 将DTO数据复制为pojo数据（其中由于images的类型不同，这个属性值复制失败）
        WmNews wmNews = new WmNews();
        BeanUtils.copyProperties(dto,wmNews);


        //2.2 将封面图片列表转为逗号分割字符串
        List<String> coverImageList = dto.getImages();
        if (coverImageList != null && coverImageList.size() > 0) {
            String coverImageStr = StringUtils.join(coverImageList, ",");
            wmNews.setImages(coverImageStr);
        }


        //2.3 如果布局方式是自动，则设置表中布局方式临时为空 -1 自动布局
        if (dto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)) {
            wmNews.setType(null);
        }


        //2.4 根据Id创建或更新文章
        ResponseResult responseResult = this.saveOrUpdateWmNews(dto, isSubmit, wmNews);
        if (responseResult != null) {
            return responseResult;
        }


        //准备工作：抽取文章内容中的全部图片地址列表
        List<String> contentImageList = extractContentImageList(dto);

        //3. 保存内容图片与文章关系（执行前提：必须是提交审核且内容图片有值）
        if (isSubmit.equals(WmNews.Status.SUBMIT.getCode()) && contentImageList.size() > 0) {
            // 保存文章与内容图片的关系
            responseResult = this.saveRelation(contentImageList, WemediaConstants.WM_CONTENT_REFERENCE, wmNews.getId());
            if (responseResult != null) {
                return responseResult;
            }
        }


        //4. 保存封面图片与文章关系
        if (isSubmit.equals(WmNews.Status.SUBMIT.getCode())) {
            responseResult = saveReationForCover(dto, contentImageList, wmNews);
            if (responseResult != null){
                return responseResult;
            }

            // 异步调用文章自动审核(异步审核的逻辑当做任务提交到线程池中执行)
            wmNewsAuditService.auditWmNews(wmNews, contentImageList);
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }


    @Autowired
    private GreenTextScan3 greenTextScan3;

    @Autowired
    private GreenImageScan greenImageScan;

    @Autowired
    private FileStorageService fileStorageService;

    @Autowired
    private IArticleClient articleClient;

    @Autowired
    private WmChannelService wmChannelService;

    @Autowired
    private WmUserService wmUserService;



    /**
     *  保存封面图片与文章关系
     */
    private ResponseResult saveReationForCover(WmNewsDto dto, List<String> contentImageList, WmNews wmNews) {
        ResponseResult responseResult;
        // 封面图片地址列表
        List<String> coverImages = dto.getImages();

        // 如果当前是自动布局，则根据自动匹配规则选择内容图片当做封面图片，决定最终布局方式  0 无图  1-2 单图（第一张） 3及其以上 三图
        if (dto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)) {
            // 内容图片数量
            int size = contentImageList.size();

            //自动规则1：数量>=3，取3张当封面图片，最终布局方式为多图布局
            if (size >= 3) {
                coverImages = contentImageList.stream().limit(3).collect(Collectors.toList());
                //wmNews.setType(3);
                wmNews.setType(WemediaConstants.WM_NEWS_MANY_IMAGE);
            } else if (size >= 1 && size < 3) {
                //自动规则2：3>数量>=1，取第1张当封面图片，最终布局方式为单图布局
                coverImages = contentImageList.stream().limit(1).collect(Collectors.toList());
                //wmNews.setType(1);
                wmNews.setType(WemediaConstants.WM_NEWS_SINGLE_IMAGE);
            } else {
                //自动规则3：数量=0，封面无图片，最终布局方式为无图布局
                coverImages = contentImageList.stream().limit(1).collect(Collectors.toList());
                //wmNews.setType(0);
                wmNews.setType(WemediaConstants.WM_NEWS_NONE_IMAGE);
            }

            //如果封面图片地址真的有值，则转为逗号分割的字符串
            if (coverImages.size() > 0) {
                String coverImageStr = StringUtils.join(coverImages, ",");
                wmNews.setImages(coverImageStr);
            }

            //更新文章的最终布局方式和封面图片
            this.updateById(wmNews);

        }

        if (coverImages.size() > 0) {
            // 保存封面图片与文章关系
            responseResult = this.saveRelation(coverImages, WemediaConstants.WM_COVER_REFERENCE, wmNews.getId());
            if (responseResult != null) {
                return responseResult;
            }
        }
        return null;
    }


    /**
     * 抽取内容中图片地址列表
     */
    private static List<String> extractContentImageList(WmNewsDto dto) {
        String content = dto.getContent();
        List<String> contentImageList = new ArrayList<>();
        List<Map> mapList = JSON.parseArray(content, Map.class);
        //List<Map> mapList = JSONArray.parseArray(content, Map.class);
        for (Map<String, String> map : mapList) {
            String type = map.get("type");
            if ("image".equals(type)) {
                String imageUrl = map.get("value");
                contentImageList.add(imageUrl);
            }
        }
        return contentImageList;
    }

    /**
     * 根据id创建或更新文章
     */
    private ResponseResult saveOrUpdateWmNews(WmNewsDto dto, Integer isSubmit, WmNews wmNews) {
        Integer userId = ThreadLocalUtil.getUserId();
        wmNews.setUserId(userId); // 用户id
        //wmNews.setEnable(1); // 暂时设置为已上架 1   未上架 0
        wmNews.setEnable(WemediaConstants.ENABLE_UP); // 暂时设置为已上架 1   未上架 0
        wmNews.setSubmitedTime(new Date()); // 提交时间
        wmNews.setStatus(isSubmit);

        // 如果Id参数无值，则创建文章
        Integer wmNewsId = dto.getId();
        if (wmNewsId == null) {
            wmNews.setCreatedTime(new Date()); // 创建时间
            this.save(wmNews);
        } else {
            // 如果Id参数有值，则更新文章删除关系

            // 判断文章是否存在
            int count = this.count(Wrappers.<WmNews>lambdaQuery().eq(WmNews::getId, wmNewsId));
            if (count <= 0) {
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "文章不存在，不能修改");
            }
            // 更新文章
            this.updateById(wmNews);
            // 删除文章和素材对应的关系
            wmNewsMaterialService.remove(Wrappers.<WmNewsMaterial>lambdaQuery().eq(WmNewsMaterial::getNewsId, wmNewsId));
        }
        return null;
    }


    /**
     * 公共方法：保存素材与文章的关系
     * imageList 素材的地址列表
     * type 0 内容引用 1 主图引用
     * wmNewsId 文章id
     */
    private ResponseResult saveRelation(List<String> imageList, int type, int wmNewsId) {
        //根据素材地址从素材表中查询素材列表
        List<WmMaterial> materialList = wmMaterialService.list(Wrappers.<WmMaterial>lambdaQuery().in(WmMaterial::getUrl, imageList));
        //判断是否所有素材地址都查询到具体的素材
        if (materialList.size() != imageList.size()) {
            return ResponseResult.errorResult(AppHttpCodeEnum.MATERIASL_REFERENCE_FAIL);
        }
        //获取所有素材的id集合
        List<Integer> materialIdList = materialList.stream().map(WmMaterial::getId).collect(Collectors.toList());
        //遍历构建素材与文章的关系数据
        List<WmNewsMaterial> wmNewsMaterialList = new ArrayList<>();
        int ord = 0;
        for (Integer materialId : materialIdList) {
            WmNewsMaterial wmNewsMaterial = new WmNewsMaterial();
            wmNewsMaterial.setMaterialId(materialId);
            wmNewsMaterial.setNewsId(wmNewsId);
            //wmNewsMaterial.setType(0); // 内容图片 0  封面图片 1
            wmNewsMaterial.setType(type); // 内容图片 0  封面图片 1
            wmNewsMaterial.setOrd(ord);
            ord++;
            wmNewsMaterialList.add(wmNewsMaterial);
        }
        // 批量保存
        wmNewsMaterialService.saveBatch(wmNewsMaterialList);

        return null;
    }

    /**
     * 查询文章列表
     */
    @Override
    public ResponseResult list(WmNewsPageReqDto dto) {
        log.info("查询文章列表开始 dto =====>>> {}", dto);
        //1.设置分页请求参数默认值
        dto.checkParam();

        //2.拼接查询条件
        LambdaQueryWrapper<WmNews> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //2.1 设置固定查询条件
        lambdaQueryWrapper.eq(WmNews::getUserId,ThreadLocalUtil.getUserId() ); //根据用户ID查询
        //2.2 拼接动态查询条件
        if(dto.getChannelId()!=null){
            lambdaQueryWrapper.eq(WmNews::getChannelId, dto.getChannelId()); //根据频道ID查询
        }
        if(dto.getStatus()!=null){
            lambdaQueryWrapper.eq(WmNews::getStatus, dto.getStatus());//根据状态查询
        }
        if(StringUtils.isNotBlank(dto.getKeyword())){
            lambdaQueryWrapper.like(WmNews::getTitle,dto.getKeyword());//根据关键词模糊查询
        }
        if(dto.getBeginPubDate()!=null && dto.getEndPubDate()!=null){
            lambdaQueryWrapper.between(WmNews::getPublishTime, dto.getBeginPubDate(), dto.getEndPubDate());//根据发布时间范围查询
        }
        //2.3 设置根据发布时间倒排序
        lambdaQueryWrapper.orderByDesc(WmNews::getPublishTime);

        //3.执行分页查询
        IPage<WmNews> page = new Page<>(dto.getPage(),dto.getSize());
        this.page(page,lambdaQueryWrapper);

        //4.封装分页响应结果
        ResponseResult responseResult = new PageResponseResult(dto.getPage(),dto.getSize(),page.getTotal());
        responseResult.setData(page.getRecords());//设置每页列表数据

        return responseResult;
    }


    /**
     * 编辑文章前回显
     */
    @Override
    public ResponseResult getNews(Integer id) {
        log.info("编辑文章前回显开始 id =====>>> {}", id);
        if (id == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        WmNews one = this.getOne(Wrappers.<WmNews>lambdaQuery().eq(WmNews::getId, id));

        return ResponseResult.okResult(one);
    }


    /**
     * 文章删除
     */
    @Transactional
    @Override
    public ResponseResult deleteNews(Integer id) {
        log.info("文章删除开始 id ====>>> {}",id);
        if (id == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "文章id不可缺少");
        }

        //根据id查询文章内容
        WmNews one = this.getOne(Wrappers.<WmNews>lambdaQuery().eq(WmNews::getId, id));
        if (one == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "文章不存在");
        }
        //判断文章状态
        if (9 == one.getStatus()) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "文章已发布，不能删除");
        }
        // 删除文章
        // 删除文章表
        this.removeById(id);

        // 删除关联表 根据文章id newsId
        WmNewsMaterial wmNewsMaterial = new WmNewsMaterial();
        wmNewsMaterial.setNewsId(one.getId());
        wmNewsMaterialService.remove(Wrappers.<WmNewsMaterial>lambdaQuery().eq(WmNewsMaterial::getNewsId, id));

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }


    @Autowired
    private KafkaTemplate kafkaTemplate;

    /**
     * 文章上下架
     */
    @Override
    public ResponseResult  downOrUp(WmNewsDto dto) {
        log.info("文章上下架开始 dto ====>>> {}", dto);
        if (dto.getId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "文章Id不可缺少");
        }
        WmNews wmNews = this.getOne(Wrappers.<WmNews>lambdaQuery().eq(WmNews::getId, dto.getId()));
        if (wmNews == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "文章不存在");
        }
        if (wmNews.getStatus() != WmNews.Status.PUBLISHED.getCode()) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "当前文章不是发布状态，不能上下架");
        }

        WmNews wmNewsDB = new WmNews();
        wmNewsDB.setId(dto.getId());
        wmNewsDB.setEnable(dto.getEnable());
        boolean b = this.updateById(wmNewsDB);
        //return b ? ResponseResult.okResult(AppHttpCodeEnum.SUCCESS) : ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR, "操作失败");

        // 生产消息到kafka
        Map map = new HashMap();
        map.put("articleId", wmNews.getArticleId()); // app文章id
        map.put("enable", dto.getEnable());

        kafkaTemplate.send(WmNewsMessageConstants.WM_NEWS_UP_OR_DOWN_TOPIC, JSON.toJSONString(map));

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }
}
